import { BasePageRequestDto, BasePageResponseDto, BaseSingleResponseDto } from "@/dtos/BaseDto";
import { Service } from "typedi";
import { Repository } from "typeorm";
import { InjectRepository } from "typeorm-typedi-extensions";
import { transformResponseDto } from "@/utils/transform";
import { System } from "@/entity/System";
import { CreateSystemDto, SystemDto, UpdateSystemDto } from "@/dtos/SystemDto";
import { DEFAULT_PAGE_INDEX, DEFAULT_PAGE_SIZE } from "@/constants/request";

@Service()
export class SystemService {
  @InjectRepository(System)
  private systemRepo!: Repository<System>;

  public async findAll(query: BasePageRequestDto): Promise<BasePageResponseDto<SystemDto>> {
    const { pageIndex = DEFAULT_PAGE_INDEX, pageSize = DEFAULT_PAGE_SIZE } = query
    const [systems, count] = await this.systemRepo.createQueryBuilder('system')
      .skip((pageIndex - 1) * pageSize)
      .take(pageSize)
      .getManyAndCount();
    const systemDtos = systems.map(item => {
      return this.transformEntity2Dto(item);
    })
    return {
      success: true,
      message: 'Get systems',
      data: systemDtos,
      total: count,
      pageIndex,
      pageSize,
    };
  }

  public async get(id: number, message = 'get system success'): Promise<BaseSingleResponseDto<SystemDto>> {
    const system = await this.systemRepo.findOne({ where: { id } });
    if (!system) {
      throw new Error('system not found');
    }
    const resSystem = this.transformEntity2Dto(system!);
    return {
      success: true,
      message: message,
      data: resSystem,
    }
  }

  public async create(system: CreateSystemDto): Promise<BaseSingleResponseDto<SystemDto>> {
    const newSystem = this.systemRepo.create({
      name: system.name,
      code: system.code,
      description: system.description,
    });
    await this.systemRepo.save(newSystem);
    const resSystem = this.transformEntity2Dto(newSystem);
    return {
      success: true,
      message: 'System created',
      data: resSystem,
    };
  }

  public async update(system: UpdateSystemDto): Promise<BaseSingleResponseDto<SystemDto>> {
    const oldSystem = await this.systemRepo.findOne({ where: { id: system.id } });
    if (!oldSystem) {
      throw new Error('System not found');
    }
    const newSystem = await this.systemRepo.update(system.id, {
      name: system.name,
      code: system.code,
      description: system.description,
    });
    if (!newSystem.affected) {
      throw new Error('update error');
    }
    return this.get(system.id, 'update success');
  }

  public async batchDelete(systemIds: number[]): Promise<BaseSingleResponseDto<boolean>> {
    const result = await this.systemRepo.delete(systemIds);
    if (!result.affected) {
      throw new Error('delete error');
    }
    return {
      success: true,
      message: 'delete success',
      data: true,
    }
  }

  private transformEntity2Dto(entity: System): SystemDto {
    return transformResponseDto<SystemDto, System>(entity, {
      name: entity.name,
      code: entity.code,
      description: entity.description,
    });
  }

}
